package top.lshaci.learning.jvm.ref;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.sql.Time;
import java.util.concurrent.TimeUnit;

/**
 * PhatomReferencTest
 *
 * @author lshaci
 * @date 2020/8/7 17:31
 * @since 1.0.0
 */
public class PhantomReferenceTest {

    /**
     * 当前类对象的声明
     */
    public static PhantomReferenceTest obj;
    /**
     * 引用队列
     */
    static ReferenceQueue<PhantomReferenceTest> phantomQueue = null;

    public static class CheckRefQueue extends Thread {
        @Override
        public void run() {
            while (true) {
                if (phantomQueue != null) {
                    PhantomReference<PhantomReferenceTest> objt = null;
                    try {
                        objt = (PhantomReference<PhantomReferenceTest>) phantomQueue.remove();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    if (objt != null) {
                        System.err.println("追踪垃圾回收过程： PhantomReferenceTest 实例被GC了");
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Thread thread = new CheckRefQueue();
        // 设为守护线程
        thread.setDaemon(true);
        thread.start();

        phantomQueue = new ReferenceQueue<>();
        obj = new PhantomReferenceTest();

        PhantomReference<PhantomReferenceTest> pr = new PhantomReference<>(obj, phantomQueue);
        // 不可获取虚引用中的对象
        System.err.println(pr.get());
        // 将强引用去除
        obj = null;
        // 第一次进行GC，由于对象可以复活，GC无法回收该对象
        System.err.println("第一次GC");
        System.gc();

        TimeUnit.SECONDS.sleep(1);
        if (obj == null) {
            System.err.println("obj is null");
        } else {
            System.err.println("obj is not null");
        }

        System.err.println("第二次GC");
        obj = null;
        System.gc(); // 一旦将obj回收，会将虚引用放到phantomQueue队列中

        TimeUnit.SECONDS.sleep(1);
        if (obj == null) {
            System.err.println("obj is null");
        } else {
            System.err.println("obj is not null");
        }

    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.err.println("调用当前类的finalize()方法");
        obj = this;
    }
}
